/*
 * PsFile.h
 *
 *  Created on: 2018年7月8日
 *      Author: zhengboyuan
 */

#ifndef PSFILE_H_
#define PSFILE_H_

#include <stdint.h>
#include <time.h>
#include <stdio.h>

#include "MFormat.h"


struct PsFilePosition
{
    int index;         /// 文件序号, 从 0 开始
    int64_t offset;    /// 文件偏移位置
    int64_t streamOffset;   /// 流对应的文件偏移位置

    int mediaType;      /// 媒体类型
    int64_t pts;        /// 时间戳
    int size;

    time_t time;        /// 流时间
    bool keyframe;      /// 是否为关键帧
};

struct PsFilePositionRange
{
    PsFilePosition beginPos;    /// 开始位置
    PsFilePosition endPos;      /// 结束位置
};


enum PsFileSeekMode
{
    kSeekFrame = 0,
    kSeekKeyFrame = 1   /// 关键帧搜索模式
};

struct PsMPacket
{
    int type;       ///
    uint8_t* data;  /// 数据指针
    int size;       /// 数据长度
    int64_t pts;    /// 时间戳
    int duration;   /// 时长
    int flags;      /// 标识
    time_t time;    /// 物理时钟, UTC时间
};

typedef bool (*PsPacketProc)(void* userdata, const PsFilePosition& pos, PsMPacket& pkt);


class PsFile
{
public:
    virtual ~PsFile() {}


    virtual bool open(const char* filepath) =0;

    virtual void close() =0;

    virtual bool isOpen() =0;

    virtual int64_t getTotalSize() =0;

//    virtual const char* getFilePath() =0;



    /**
     * 获取总的位置范围
     * @param beginPos
     * @param endPos
     * @return
     */
    virtual bool getTotalPositionRange(PsFilePosition& beginPos, PsFilePosition& endPos) =0;

    /**
     * 获取开始位置
     * @return
     */
    virtual PsFilePosition getBeginPos() =0;

    /**
     * 获取结束位置
     * @return
     */
    virtual PsFilePosition getEndPos() =0;

    /**
     * 获取开始关键帧位置
     * @return
     */
    virtual PsFilePosition getBeginKeyPos() =0;

    /**
     * 获取关键帧位置范围
     * @param beginPos
     * @param endPos
     * @return
     */
    virtual bool getTotalKeyFrameRange(PsFilePosition& beginPos, PsFilePosition& endPos) =0;

    /**
     * 定位到指定时间.
     * 该API会改变当前的时间范围的开始位置
     * @param t         时钟, UTC时间
     * @param seekMode  搜索模式
     * @param pos
     * @return true 表示成功
     */
    virtual bool seek(time_t t, PsFileSeekMode seekMode, PsFilePosition& pos) =0;

    /**
     * 定位到指定时间范围.
     * 该API会改变当前的时间范围
     * @param t         时钟, UTC时间
     * @param duration  时间范围长度, 单位为秒
     * @param seekMode  搜索模式
     * @param beginPos  开始位置
     * @param endPos    结束位置
     * @return true 表示成功
     */
    virtual bool seekRange(time_t t, uint32_t duration, PsFileSeekMode seekMode, PsFilePosition& beginPos, PsFilePosition& endPos) =0;

    /**
     * 读取媒体包
     * @param pkt   媒体包
     * @return  true 表示成功
     */
    virtual bool read(const PsFilePosition& pos, PsMPacket& pkt) =0;

    /**
     * 读取某个范围的媒体包. 回调函数 PsPacketProc 返回 false 就中断不在继续读
     * @param beginPos
     * @param endPos
     * @param proc
     * @param userdata
     * @return
     */
    virtual bool readRange(const PsFilePosition& beginPos, const PsFilePosition& endPos, PsPacketProc proc, void* userdata) =0;

    /**
     * 获取媒体格式
     * @param fmt   媒体格式
     * @return
     */
    virtual bool getMediaFormat(MFormat& fmt) =0;



};

#endif /* PSFILE_H_ */
